/*
 * $RCSfile: TablePanel.java,v $
 * $Revision: 1.1 $
 * $Date: 2009-10-12 $
 *
 * Copyright (C) 2005 Skin, Inc. All rights reserved.
 *
 * This software is the proprietary information of Skin, Inc.
 * Use is subject to license terms.
 */
package com.skin.generate.gui.table;

import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.skin.generate.GenericGenerator;
import com.skin.generate.Template;
import com.skin.generate.gui.Constant;
import com.skin.generate.gui.GeneratorDialog;
import com.skin.generate.gui.LocalStorage;
import com.skin.generate.gui.ProgressDialog;
import com.skin.generate.gui.SwingManager;
import com.skin.generate.gui.container.BaseFrame;
import com.skin.generate.gui.container.BasePanel;
import com.skin.generate.gui.event.ClickListener;
import com.skin.generate.gui.event.ListClickListener;
import com.skin.generate.gui.util.SqlFile;
import com.skin.generate.gui.util.TableUtil;
import com.skin.generate.gui.util.TemplateUtil;
import com.skin.webcat.database.Table;

/**
 * <p>Title: TablePanel</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * @author xuesong.net
 * @version 1.0
 */
public class TableListPanel extends BasePanel {
    private static final long serialVersionUID = 1L;
    JTable jTable;
    JButton codeButton;
    JButton checkAllButton;
    JButton refreshButton;
    TableListModel tableModel;
    GeneratorDialog generatorDialog;
    ProgressDialog progressDialog;
    static final Logger logger = LoggerFactory.getLogger(TableListPanel.class);

    /**
     * @param frame
     */
    public TableListPanel(BaseFrame frame) {
        super(frame);
        this.init();
    }

    /**
     * @param params
     */
    @Override
    public void load(Map<String, Object> params) {
        this.checkAllButton.setText("全部取消");
        List<Table> tableList = this.getTableList(params, false);
        this.setTableList(tableList);
    }

    /**
     * @param params
     * @param detail
     * @return List<Table>
     */
    private List<Table> getTableList(Map<String, Object> params, boolean detail) {
        logger.info("params: {}", JSON.toJSONString(params));
        String connectionName = (String)(params.get("name"));

        if(connectionName != null) {
            try {
                return TableUtil.getTableList(connectionName, detail);
            }
            catch(Exception e) {
                logger.error(e.getMessage(), e);
                error(e);
            }
        }

        String path = (String)(params.get("path"));

        if(path != null) {
            try {
                return SqlFile.getTableList(path);
            }
            catch(Exception e) {
                logger.error(e.getMessage(), e);
                error(e);
            }
        }
        return null;
    }

    /**
     * @param tableList
     * @param tableNameList
     * @return List<Table>
     */
    private List<Table> filter(List<Table> tableList, List<String> tableNameList) {
        if(tableNameList == null) {
            return tableList;
        }

        List<Table> result = new ArrayList<Table>();

        if(tableList != null) {
            for(Table table : tableList) {
                if(tableNameList.contains(table.getTableName())) {
                    result.add(table);
                }
            }
        }
        return result;
    }

    /**
     * init
     */
    public void init() {
        JScrollPane jScrollPane = new JScrollPane();
        jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        jScrollPane.setViewportView(this.getJTable());

        this.setLayout(new java.awt.BorderLayout());
        this.add(getJToolBar(), java.awt.BorderLayout.NORTH);
        this.add(jScrollPane, java.awt.BorderLayout.CENTER);
    }

    /**
     * @return JMenuBar
     */
    JToolBar getJToolBar() {
        JToolBar jToolBar = new JToolBar();
        jToolBar.setFloatable(false);
        jToolBar.setBorder(new EmptyBorder(4, 4, 4, 4));
        jToolBar.add(this.getCheckAllButton());
        jToolBar.add(this.getCodeButton());
        jToolBar.add(this.getRefreshButton());
        return jToolBar;
    }

    JButton getCheckAllButton() {
        if(this.checkAllButton == null) {
            this.checkAllButton = new JButton("全部取消");
            this.checkAllButton.setFont(SwingManager.getDefaultFont());
            this.checkAllButton.setMargin(new Insets(0, 10, 0, 10));
            this.checkAllButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.checkAllButton.addActionListener(new ClickListener() {
                @Override
                public void click(ActionEvent actionEvent) {
                    checkAll();
                }
            });
        }
        return this.checkAllButton;
    }

    JButton getCodeButton() {
        if(this.codeButton == null) {
            this.codeButton = new JButton("批量生成");
            this.codeButton.setFont(SwingManager.getDefaultFont());
            this.codeButton.setMargin(new Insets(0, 10, 0, 10));
            this.codeButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.codeButton.addActionListener(new ClickListener() {
                @Override
                public void click(ActionEvent actionEvent) {
                    showGenerateDialog();
                }
            });
        }
        return this.codeButton;
    }

    JButton getRefreshButton() {
        if(this.refreshButton == null) {
            this.refreshButton = new JButton("刷 新");
            this.refreshButton.setFont(SwingManager.getDefaultFont());
            this.refreshButton.setMargin(new Insets(0, 10, 0, 10));
            this.refreshButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.refreshButton.addActionListener(new ClickListener() {
                @Override
                public void click(ActionEvent actionEvent) {
                    reload();
                }
            });
        }
        return this.refreshButton;
    }

    /**
     * @return JTable
     */
    protected JTable getJTable() {
        if(this.tableModel == null) {
            this.tableModel = new TableListModel();
        }

        if(this.jTable == null) {
            this.jTable = new JTable(this.tableModel);

            ListClickListener listClickListener = new ListClickListener() {
                @Override
                public void click(ListSelectionEvent e) {
                    if(e.getValueIsAdjusting() == false) {
                        setEditing();
                    }
                }
            };

            this.jTable.setFont(SwingManager.getDefaultFont());
            this.jTable.getSelectionModel().addListSelectionListener(listClickListener);
            this.jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            this.jTable.setRowHeight(SwingManager.getScaleSize(22));
        }
        return this.jTable;
    }

    /**
     * @param text
     * @return JLabel
     */
    public JLabel getJLabel(String text) {
        JLabel label = new JLabel(text);
        label.setFont(SwingManager.getDefaultFont());
        return label;
    }

    /**
     * @param tableList
     */
    public void setTableList(List<Table> tableList) {
        Object[][] data = new Object[tableList.size()][3];

        for(int i = 0; i < tableList.size(); i++) {
            Table table = tableList.get(i);
            data[i] = new Object[3];
            data[i][0] = Boolean.TRUE;
            data[i][1] = table.getTableName();
            data[i][2] = table.getRemarks();
        }
        this.codeButton.setEnabled(true);
        this.tableModel.setData(data);
        this.jTable.updateUI();
        this.setEditing();
    }

    /**
     * set editing
     */
    public void setEditing() {
        int rowCount = this.jTable.getRowCount();
        int selectedRow = this.jTable.getSelectedRow();

        if(rowCount < 1) {
            return;
        }

        if(selectedRow < 0) {
            selectedRow = 0;
        }

        if(selectedRow > (rowCount - 1)) {
            selectedRow = rowCount - 1;
        }
        this.jTable.setRowSelectionInterval(selectedRow, selectedRow);
        this.jTable.editCellAt(this.jTable.getSelectedRow(), 2);
    }

    void checkAll() {
        Boolean checked = Boolean.TRUE;
        String text = this.checkAllButton.getText();

        if(text.equals("全部选中")) {
            checked = Boolean.TRUE;
            this.checkAllButton.setText("全部取消");
        }
        else {
            checked = Boolean.FALSE;
            this.checkAllButton.setText("全部选中");
        }

        for(int i = 0; i < this.jTable.getRowCount(); i++) {
            this.jTable.setValueAt(checked, i, 0);
        }
    }

    void showGenerateDialog() {
        final List<String> tableNameList = this.getSelectedTableList();

        if(tableNameList == null || tableNameList.isEmpty()) {
            this.message("请选择表！");
            return;
        }

        if(this.generatorDialog == null) {
            this.generatorDialog = new GeneratorDialog(this.frame, Constant.APP_NAME, true);
            this.generatorDialog.setIconImage(SwingManager.getImage("resource/icon.gif"));
        }

        this.generatorDialog.setBatchMode(true);
        this.generatorDialog.setAuthor(System.getProperty("user.name"));
        int returnValue = this.generatorDialog.open();

        if(returnValue != GeneratorDialog.ENSURE) {
            return;
        }

        final boolean wrapper = this.generatorDialog.getWrapper();
        final String encoding = this.generatorDialog.getEncoding();
        final String author = this.generatorDialog.getAuthor();
        final String template = this.generatorDialog.getTemplate();
        final String output = this.generatorDialog.getOutputPath();

        /**
         * 显示进度条
         */
        if(this.progressDialog == null) {
            this.progressDialog = new ProgressDialog(this.frame, "进度", false);
            this.progressDialog.setIconImage(SwingManager.getImage("resource/icon.gif"));
        }

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                generate(tableNameList, template, wrapper, encoding, author, output);
            }
        };
        this.progressDialog.reset();
        this.progressDialog.setText("正在读取表结构，请稍候...");
        this.progressDialog.open(runnable);
    }

    /**
     * 该方法在单独的非UI线程中执行
     * 所以该方法内对任何UI元素的操作都应该再次调用SwingUtilities.invokeLater, 使之在UI线程中执行
     * 暂时先不这么操作, 一般没问题.
     * @param tableNameList
     * @param templateName
     * @param wrapper
     * @param encoding
     * @param author
     * @param output
     */
    void generate(List<String> tableNameList, String templateName, boolean wrapper, String encoding, String author, String output) {
        try {
            List<Table> tableList = this.getTableList(this.params, true);
            tableList = this.filter(tableList, tableNameList);

            if(tableList == null || tableList.isEmpty()) {
                this.progressDialog.close();
                this.message("系统错误，请选择表！");
                return;
            }

            if(wrapper) {
                for(Table table : tableList) {
                    TableUtil.setWrapper(table);
                }
            }

            String home = TemplateUtil.getTemplateDirectory();
            List<Template> templates = TemplateUtil.getTemplateList(templateName);

            if(templates == null || templates.size() < 1) {
                this.progressDialog.close();
                this.error("没有可用的模板！");
                return;
            }

            float count = 0.0f;
            boolean complete = true;
            GenericGenerator generator = new GenericGenerator(home, output);
            generator.setTemplates(templates);
            generator.setEncoding(encoding);
            generator.setAuthor(author);

            for(Table table : tableList) {
                if(!this.progressDialog.getRunning()) {
                    complete = false;
                    break;
                }

                logger.info("tableName: {}", table.getTableName());
                String xml = TableUtil.toXml(table);
                LocalStorage.write(new File(output, table.getClassName() + ".xml").getCanonicalFile(), xml, "utf-8");
                generator.generate(table);

                count += 1.0f;
                int pregress = (int)(count / tableList.size() * 100);
                this.progressDialog.setText(pregress + "%  正在处理：" + table.getTableName());
                this.progressDialog.setString(pregress + "%");
                this.progressDialog.setProgress((count / tableList.size()));
            }
            this.progressDialog.close();

            if(complete) {
                this.message("代码生成完成: " + new File(output).getCanonicalPath());
            }
        }
        catch(Exception e) {
            logger.warn(e.getMessage(), e);
            this.error(e);
        }
        finally {
            this.progressDialog.close();
        }
    }

    /**
     * @return List<String>
     */
    List<String> getSelectedTableList() {
        List<String> tableList = new ArrayList<String>();

        for(int i = 0; i < this.jTable.getRowCount(); i++) {
            Boolean checked = (Boolean)this.jTable.getValueAt(i, 0);
            String tableName = (String)this.jTable.getValueAt(i, 1);

            if(checked.booleanValue() == true) {
                tableList.add(tableName);
            }
        }
        return tableList;
    }
}
